package com.epoch.platform.sys.generator.util;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;

import com.epoch.base.util.DateUtils;
import com.epoch.platform.sys.generator.entity.ColumnEntity;
import com.epoch.platform.sys.generator.entity.TableEntity;
import com.google.common.collect.Lists;
import com.jfinal.plugin.activerecord.Record;

public class GenUtils {

	public static void generatorCode(Record table, List<Record> columns,
			ZipOutputStream zip) {
		Configuration config = getConfig();
		String target = "base";
		if(table.getStr("tableName") != null && !table.getStr("tableName").contains("_")) {
			target = table.getStr("tableName");
		}else {
			target = table.getStr("tableName").substring(0, table.getStr("tableName").indexOf("_"));
		}
		
		config.setProperty("tablePrefix", target);
		TableEntity tableEntity = new TableEntity();
		tableEntity.setTableName(table.get("tableName"));
		tableEntity.setComments(table.get("tableComment"));
		tableEntity.setClassName(getClassName(tableEntity.getTableName()));
		tableEntity.setClassNameLower(tableEntity.getClassName());
		tableEntity.setSubName(getSubName(tableEntity.getTableName()));
		// 列信息
		List<ColumnEntity> columsList = new ArrayList<>();
        for(Record column : columns){
            ColumnEntity columnEntity = new ColumnEntity();
            columnEntity.setColumnName(column.getStr("columnName").toUpperCase());
            columnEntity.setColumnNameLower(column.getStr("columnName").toLowerCase());
            columnEntity.setDataType(column.getStr("dataType"));
            columnEntity.setComments(column.getStr("columnComment"));
            columnEntity.setExtra(column.getStr("extra"));
            //是否主键
            if("PRI".equalsIgnoreCase(column.get("columnKey")) && tableEntity.getPk() == null){
                tableEntity.setPk(columnEntity);
            }
            columsList.add(columnEntity);
        }
        tableEntity.setColumns(columsList);
        for (Iterator<ColumnEntity> iterator = columsList.iterator(); iterator.hasNext();) {
			ColumnEntity columnEntity = iterator.next();
			if(columnEntity.getColumnName().equalsIgnoreCase("ID")) {
				iterator.remove();
			}
		}
        List<List<ColumnEntity>> subSets = Lists.partition(columsList, 3);
        tableEntity.setSubColumns(subSets);
        //没主键，则第一个字段为主键
        if(tableEntity.getPk() == null){
            tableEntity.setPk(tableEntity.getColumns().get(0));
        }
        //设置velocity资源加载器
        Properties prop = new Properties();  
        prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        String fileDir = Thread.currentThread().getContextClassLoader()
        		.getResource("").getPath();
        prop.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, fileDir);
        Velocity.init(prop);
        //封装模板数据
        Map<String, Object> map = new HashMap<>();
        map.put("tableName", tableEntity.getTableName());
        map.put("comments", tableEntity.getComments());
        map.put("pk", tableEntity.getPk());
        map.put("className", tableEntity.getClassName());
        map.put("classNameLower", StringUtils.uncapitalize(tableEntity.getClassName()));
        map.put("subName", tableEntity.getSubName());
        map.put("columns", tableEntity.getColumns());
        map.put("subColumns", tableEntity.getSubColumns());
        map.put("package", config.getString("package"));
        map.put("subpackage", config.getString("tablePrefix").replace("_", ""));
        map.put("author", config.getString("author"));
        map.put("email", config.getString("email"));
        map.put("jinhao", "#");
        map.put("daole", "$");
        map.put("zuokuohao", "{");
        map.put("youkuohao", "}");
        map.put("datetime", DateUtils.format(new Date(), DateUtils.DATEFORMAT_YYYY_MM_DD_HH_MM_SS));
        VelocityContext context = new VelocityContext(map);
        //获取模板列表
        List<String> templates = getTemplates();
        for(String template : templates){
            //渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, "UTF-8");
            tpl.merge(context, sw);
            try {
                //添加到zip
                zip.putNextEntry(new ZipEntry(getFileName(template, tableEntity.getClassName(), config.getString("package"), config.getString("tablePrefix"),map)));  
                IOUtils.write(sw.toString(), zip, "UTF-8");
                IOUtils.closeQuietly(sw);
                zip.closeEntry();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
	}
	
	private static String getClassName(String tableName) {
		String[] names = tableName.split("_");
		StringBuffer buffer = new StringBuffer();
		for (String string : names) {
			buffer.append(StringUtils.capitalize(string.toLowerCase()));
		}
		return buffer.toString();
		
	}
	
	private static String getSubName(String tableName) {
		if(tableName.contains("_")) {
			String[] names = tableName.split("_");
			StringBuffer buffer = new StringBuffer();
			for (int i = 1; i < names.length; i++) {
				String string = names[i];
				buffer.append(StringUtils.uncapitalize(string.toLowerCase()));
			}
			return buffer.toString();
		}
		return tableName;
	}

	public static Configuration getConfig() {
		try {
			return new PropertiesConfiguration("generator.properties");
		} catch (ConfigurationException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static List<String> getTemplates() {
		List<String> templates = new ArrayList<String>();
		templates.add("template/Dao.java.vm");
		templates.add("template/Controller.java.vm");
		templates.add("template/template.sql.vm");
		templates.add("template/tab.html.vm");
		templates.add("template/list.html.vm");
		templates.add("template/edit.html.vm");
		return templates;
	}

	public static String getFileName(String template, String className, String packageName, String moduleName,Map<String, Object> map) {
		String packagePath = "main" + File.separator + "java" + File.separator;
		if (StringUtils.isNotBlank(packageName)) {
			packagePath += packageName.replace(".", File.separator) + File.separator + moduleName + File.separator;
		}
		if (template.contains("Dao.java.vm")) {
			return packagePath + "dao" + File.separator + className + "Dao.java";
		}
		if (template.contains("Controller.java.vm")) {
			return packagePath + "controller" + File.separator + className + "Controller.java";
		}
		if (template.contains("tab.html.vm")) {
			return "main" + File.separator+ "WEB-INF" + File.separator  + "bs" + File.separator + map.get("subpackage").toString() +File.separator 
					+ map.get("subName").toString()+ File.separator +map.get("tableName").toString().toLowerCase()+"_tab.html";
		}
		if (template.contains("list.html.vm")) {
			return "main" + File.separator+ "WEB-INF" + File.separator  + "bs" + File.separator + map.get("subpackage").toString() +File.separator 
					+ map.get("subName").toString()+ File.separator +map.get("tableName").toString().toLowerCase()+"_list.html";
		}
		if (template.contains("edit.html.vm")) {
			return "main" + File.separator+ "WEB-INF" + File.separator  + "bs"  + File.separator + map.get("subpackage").toString() +File.separator 
					+ map.get("subName").toString()+ File.separator +map.get("tableName").toString().toLowerCase()+"_edit.html";
		}
		if (template.contains("template.sql.vm")) {
			return className + ".sql";
		}
		return null;
	}
}
